`include "constantes.v" 

module hd (
clk,
reset,
HDSys_ACK,
HDSys_Adr,
HDSys_Ctl,
HDSys_Req,	   
HD_Data_O,
SysHD_Gnt,		 
Bus_Data_I,
Bus_Data_O,
Bus_Adr,
Bus_Ctl,
Bus_ACK,
Bus_Gnt,
HD_Int,
HD_Int_ACK
);

integer i, r, file;
reg [80*8:1] file_name; 

reg [`TAM_BDAT:0] mem [0:`TAM_HD];

input			clk;
input			reset;

input [`TAM_BADR:0]		Bus_Adr;
input [`TAM_BCTL:0]		Bus_Ctl;
input [`TAM_BDAT:0]		Bus_Data_I;
input 			  		Bus_ACK;
input 			  		Bus_Gnt;
input [`TAM_BDAT:0]		Bus_Data_O;

output [`TAM_BDAT:0]	HD_Data_O;
output [`TAM_BADR:0]	HDSys_Adr;
reg	[`TAM_BADR:0]		HDSys_Adr;
output [`TAM_BCTL:0]	HDSys_Ctl;
reg	[`TAM_BCTL:0]		HDSys_Ctl;

output					HDSys_ACK;
reg 					HDSys_ACK;
output					HDSys_Req;
reg 		  			HDSys_Req;
input  					SysHD_Gnt;

reg    [`TAM_BDAT:0]	HD_Data_I;
reg    [`TAM_BDAT:0]	HD_Data_O;


//16 bits regs
reg		[`TAM_REG:0]	RCon_Disk;
reg		[`TAM_REG:0]	RTam_Disk;
reg		[`TAM_REG:0] 	RCara_Disk;
reg		[`TAM_REG:0]	RPista_Disk;
reg		[`TAM_REG:0]	RSector_Disk;
reg		[21:0]			RDir_Mem;
reg 					HD_increment;

//Interrupciones
output		HD_Int;
reg 		HD_Int;
input       HD_Int_ACK;


initial begin
   RCon_Disk = 0;
   RTam_Disk = 0;
   RCara_Disk = 0;
   RPista_Disk = 0;
   RSector_Disk = 0;
   RDir_Mem = 0;
   HD_increment = 0;
   HDSys_Req = 0;
   HD_Int = 0;
   HD_Data_O = 0;
   HD_Data_I = 0;
   HDSys_Adr = 0;
   HDSys_Ctl = 0;
   HDSys_ACK = 0;
   
   file_name = "program.bin"; 
   file = $fopen("program.bin", "r");
   i = $fread(file, mem[0]); 
   $display("Loaded %0d entries \n", i);
   $fclose(file); 
   $stop; 
   
	
end

always @ (negedge reset)
begin
   RCon_Disk = 0;
   RTam_Disk = 0;
   RPista_Disk = 0;
   RCara_Disk = 0;
   RSector_Disk = 0;
   RDir_Mem = 0;
   HD_increment = 0;
   HDSys_Req = 0;
   HD_Int = 0;
   HD_Data_O = 0;
   HD_Data_I = 0;
   HDSys_Adr = 0;
   HDSys_Ctl = 0;
   HDSys_ACK = 0;
end 


always @(Bus_Adr) begin 
	if (Bus_Ctl == `OUT_WB)
	begin
//	$display(" FAIG UN OUT! ");
		case (Bus_Adr)
			`RCON_DISK :
				begin
//				$display(" RCON_DISK ");
				RCon_Disk = Bus_Data_O[`TAM_REG:0];
				end
			`RTAM_DISK :
				begin
//				$display(" RTAM_DISK ");
				RTam_Disk <= Bus_Data_O[`TAM_REG:0];	
				end
			`RCARA_DISK :
				begin
//				$display(" RCARA_DISK ");
				RCara_Disk <= Bus_Data_O[`TAM_REG:0];	
				end
			`RPISTA_DISK :
				begin
//			  $display(" RPISTA_DISK ");
				RPista_Disk <= Bus_Data_O[`TAM_REG:0];	
				end
			`RSECTOR_DISK :
				begin
//				$display(" RSECTOR_DISK ");
				RSector_Disk <= Bus_Data_O[`TAM_REG:0];	
				end
			`RDIR_MEM :
				begin
//				$display(" RDIR_MEM ");
				RDir_Mem <= Bus_Data_O[`TAM_BADR:0];	
				end
		endcase
	#10 HDSys_ACK = 1;
	end
end

always @(posedge clk) begin
				if(RCon_Disk == `HD_WRITE_MASK  && RTam_Disk > 0)
						begin
						//Mandar el bus para escritura a memoria
//						$display (" WRITE ");
						HDSys_Req = 1;
						HD_Data_O = mem [(RSector_Disk)+(RPista_Disk<<14)+(RCara_Disk<<26)];
						HDSys_Adr = RDir_Mem;
						HDSys_Ctl = `READ_MASK;
//						$display (HD_Data_O);
				end
				if (RCon_Disk == `HD_READ_MASK  && RTam_Disk > 0)
						begin
						//Mandar el bus para lectura a memoria
//						$display (" Read ");
						HDSys_Req = 1;
						HDSys_Adr = RDir_Mem; 
						HDSys_Ctl = `WRITE_MASK;
						end
end

always @(posedge Bus_ACK)
begin
	if (SysHD_Gnt == 1)
	begin
//		$display("ya tiene Grant");
  		if (RCon_Disk == `HD_WRITE_MASK)
			begin
//				$display("entro write");
				HDSys_Req = 0;
				RTam_Disk = RTam_Disk - 1;			  
				if (RTam_Disk == 0) begin
					RCon_Disk = 0;
					HD_Int = 1;
				end else begin
					RDir_Mem = RDir_Mem + 1;
					HD_increment = 1;// incrementar a u el sector cara disc
				end 
//				$display("Transferencia write END");
			end
		if (RCon_Disk == `HD_READ_MASK)
			begin			   
				$display("entro read");
				mem [(RSector_Disk)+(RPista_Disk<<14)+(RCara_Disk<<26)] = Bus_Data_I;
				#10 HDSys_Req = 0;
				if (RTam_Disk == 0) begin	
					RCon_Disk = 0;
				end else begin
					RTam_Disk = RTam_Disk - 1;
					RDir_Mem = RDir_Mem + 1;
					HD_increment = 1;
				end
//				$display("Transferencia Read End");
			end
	end
end

always @(posedge HD_Int_ACK)
begin			  
	   //Si WB ha recibido la senal de interupcion
	   HD_Int = 0;
end

always @(posedge HD_increment)
begin
	if(RSector_Disk==`NUM_SECTORES)
	begin
		if(RPista_Disk==`NUM_PISTAS)
		begin
			if(RCara_Disk==0) // si fue 1 se salir de rango
			begin
			RCara_Disk = 1;
			RPista_Disk = 0;
			RSector_Disk = 0;
			end	
		end
		else
		begin
		RPista_Disk = RPista_Disk + 1;
		RSector_Disk = 0;
		end
      end
	else
	begin
	RSector_Disk = RSector_Disk + 1;
	end
HD_increment = 0;
end

always @(negedge Bus_Gnt)
begin
		HDSys_ACK = 0;
end
endmodule